/*
 * jesd_core.c
 *
 *  Created on: 2020��9��9��
 *      Author: orihard
 */
#include <stdio.h>
#include "delay.h"
#include "jesd_core.h"

jesd_core tx_jesd;
jesd_core rx_jesd;
jesd_core orx_jesd;
jesd_core_array jesd_array;

/***************************************************************************//**
* @brief jesd_read
*******************************************************************************/
int32_t jesd_read(jesd_core core, uint32_t reg_addr, uint32_t *reg_data)
{
	*reg_data = ad_reg_read((core.base_address + reg_addr));

	return 0;
}

/***************************************************************************//**
* @brief jesd_write
*******************************************************************************/
int32_t jesd_write(jesd_core core, uint32_t reg_addr, uint32_t reg_data)
{
	ad_reg_write((core.base_address + reg_addr), reg_data);

	return 0;
}

/***************************************************************************//**
* @brief jesd_init
*******************************************************************************/
int32_t jesd_setup(jesd_core core)
{
	uint32_t status;
	status = jesd_write(core, JESD204_REG_TRX_RESET, JESD204_TRX_GT_WDT_DIS | JESD204_TRX_RESET);
	if(status < 0){
		printf("JESD204_REG_TRX_RESET write failed !");
		return -1;
	}

	status = jesd_write(core, JESD204_REG_TRX_ILA_SUPPORT, JESD204_TRX_ILA_EN);
	if(status < 0){
		printf("JESD204_REG_TRX_ILA_SUPPORT write failed !");
		return -1;
	}

	status = jesd_write(core, JESD204_REG_TRX_SCRAMBLING, core.scramble_enable);
	if(status < 0){
		printf("JESD204_REG_TRX_SCRAMBLING write failed !");
		return -1;
	}

	status = jesd_write(core, JESD204_REG_TRX_SYSREF_HANDLING, JESD204_TRX_SYSREF_ALWAYSON |
			JESD204_TRX_SYSREF_DELAY(0) |
			JESD204_TRX_SYSREF_ONRESYNC);
	if(status < 0){
		printf("JESD204_REG_TRX_SYSREF_HANDLING write failed !");
		return -1;
	}

	status = jesd_write(core, JESD204_REG_TRX_OCTETS_PER_FRAME,
					 JESD204_TRX_OCTETS_PER_FRAME(core.octets_per_frame));
	if(status < 0){
		printf("JESD204_REG_TRX_OCTETS_PER_FRAME write failed !");
		return -1;
	}

	status = jesd_write(core, JESD204_REG_TRX_FRAMES_PER_MULTIFRAME,
					 JESD204_TRX_FRAMES_PER_MULTIFRAME(core.frames_per_multiframe));
	if(status < 0){
		printf("JESD204_REG_TRX_FRAMES_PER_MULTIFRAME write failed !");
		return -1;
	}

	status = jesd_write(core, JESD204_REG_TRX_SUBCLASS_MODE,
					 JESD204_TRX_SUBCLASS_MODE(core.subclass_mode));
	if(status < 0){
		printf("JESD204_REG_TRX_SUBCLASS_MODE write failed !");
		return -1;
	}

    return(0);
}

/***************************************************************************//**
* @brief jesd_read_status
*******************************************************************************/
int32_t jesd_core_status(jesd_core core)
{
	uint32_t status;
	int32_t timeout;
	int32_t ret;
	uint8_t link;

	timeout = 100;
	do {
		mdelay(1);
		jesd_read(core, JESD204_REG_TRX_RESET, &status);
		status &= JESD204_TRX_RESET;
	} while ((timeout--) && (status == JESD204_TRX_RESET));

	if (status == JESD204_TRX_RESET) {
		printf("%s jesd_status: jesd reset not completed!\n", __func__);
		return -1;
	}

	if (core.subclass_mode >= 1) {
		timeout = 100;
		do {
			mdelay(1);
			jesd_read(core, JESD204_REG_TRX_SYNC_STATUS, &status);
			status &= JESD204_TRX_SYSREF_CAPTURED;
		} while ((timeout--) && (status != JESD204_TRX_SYSREF_CAPTURED));

		if (status != JESD204_TRX_SYSREF_CAPTURED) {
			printf("%s jesd_status: missing SYS_REF!\n", __func__);
			return -1;
		}
	}

	timeout = 100;
	do {
		mdelay(1);
		jesd_read(core, JESD204_REG_TRX_SYNC_STATUS, &status);
		status &= JESD204_TRX_SYNC_ACHIEVED;
	} while ((timeout--) && (status != JESD204_TRX_SYNC_ACHIEVED));

	if (status != JESD204_TRX_SYNC_ACHIEVED) {
		printf("%s jesd_status: Link SYNC not achieved!\n", __func__);
		return -1;
	}

	if (core.rx_tx_n == 0)
		return 0;

	jesd_read(core, JESD204_REG_RX_LINK_ERROR_STATUS, &status);
	for (link = 0; link < 8; link++) {
		if (status & JESD204_RX_LINK_K_CH_ERR(link)) {
			printf("%s Link %d: K_CH_ERR\n", __func__, link);
			ret = -1;
		}
		if (status & JESD204_RX_LINK_DISP_ERR(link)) {
			printf("%s Link %d: DISP_ERR\n", __func__, link);
			ret = -1;
		}
		if (status & JESD204_RX_LINK_NOT_IN_TBL_ERR(link)) {
			printf("%s Link %d: NOT_IN_TBL_ERR\n", __func__, link);
			ret = -1;
		}
	}

	if (status & JESD204_RX_LINK_LANE_ALIGN_ERR_ALARM) {
		printf("%s jesd_status: frame alignment error!\n", __func__);
		ret = -1;
	}

	if (status & JESD204_RX_LINK_SYSREF_LMFC_ALARM) {
		printf("%s jesd_status: sysref alignment error!\n", __func__);
		ret = -1;
	}

	if (status & JESD204_RX_LINK_BUFF_OVF_ALARM) {
		printf("%s jesd_status: receive buffer overflow error!\n", __func__);
		ret = -1;
	}

	return(ret);
}
